#include "lcd.h"

#define USE_SPI_DMA

uint8_t lcd_disp_area[LCD_WIDTH * 2] = {0};


void lcd_gpio_init(void)
{
    HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_SET);
    HAL_Delay(10);
    HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_RESET);
    HAL_Delay(50);
    HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_SET);
    HAL_Delay(100);
}

void LCD_SendCommand(uint8_t command) {
    HAL_GPIO_WritePin(rs_port, rs_pin, GPIO_PIN_RESET);
    HAL_SPI_Transmit_DMA(&hspi1, &command, 1);
}

void LCD_SendData(uint8_t data) {
    HAL_GPIO_WritePin(rs_port, rs_pin, GPIO_PIN_SET);
	
	#ifdef USE_SPI_DMA
    HAL_SPI_Transmit_DMA(&hspi1, &data, 1);
	#else
		HAL_SPI_Transmit(&hspi1, &data, 1,HAL_MAX_DELAY);
	#endif
}

void LCD_SendDataBuf(uint8_t * data,size_t buff_size) {
    HAL_GPIO_WritePin(rs_port, rs_pin, GPIO_PIN_SET);
	
	#ifdef USE_SPI_DMA
    HAL_SPI_Transmit_DMA(&hspi1, data, buff_size);
	#else
		HAL_SPI_Transmit(&hspi1, data, buff_size,HAL_MAX_DELAY);
	#endif
}

void send_pixel_data(uint16_t color){
    uint8_t temp[2] = {0};
    temp[0] = color >> 8;
    temp[1] = color & 0xFF;
    HAL_SPI_Transmit_DMA(&hspi1, temp, 2);
}

void lcd_init(void) {
    lcd_gpio_init();
	
	  HAL_GPIO_WritePin(cs_port, cs_pin, GPIO_PIN_RESET);

    LCD_SendCommand(0xFE);
    LCD_SendCommand(0xEF);
    
    LCD_SendCommand(0xEB);
    LCD_SendData(0x14);
    
    LCD_SendCommand(0x84);
    LCD_SendData(0x40);
    
    LCD_SendCommand(0x88);
    LCD_SendData(0x0A);
    
    LCD_SendCommand(0x89);
    LCD_SendData(0x21);
    
    LCD_SendCommand(0x8A);
    LCD_SendData(0x00);
    
    LCD_SendCommand(0x8B);
    LCD_SendData(0x80);
    
    LCD_SendCommand(0x8C);
    LCD_SendData(0x01);
    
    LCD_SendCommand(0x8D);
    LCD_SendData(0x01);
    
    LCD_SendCommand(0xB6);
    LCD_SendData(0x20);
    
    LCD_SendCommand(0x36);
    LCD_SendData(0x48);
    
    LCD_SendCommand(0x3A);
    LCD_SendData(0x05);
    
    
    LCD_SendCommand(0x90);
    LCD_SendData(0x08);
    LCD_SendData(0x08);
    LCD_SendData(0x08);
    LCD_SendData(0x08);
    
    LCD_SendCommand(0xBD);
    LCD_SendData(0x06);
    
    LCD_SendCommand(0xBC);
    LCD_SendData(0x00);
    
    LCD_SendCommand(0xFF);
    LCD_SendData(0x60);
    LCD_SendData(0x01);
    LCD_SendData(0x04);
    
    LCD_SendCommand(0xC3);
    LCD_SendData(0x13);
    LCD_SendCommand(0xC4);
    LCD_SendData(0x13);
    
    LCD_SendCommand(0xC9);
    LCD_SendData(0x22);
    
    LCD_SendCommand(0xBE);
    LCD_SendData(0x11);
    
    LCD_SendCommand(0xE1);
    LCD_SendData(0x10);
    LCD_SendData(0x0E);
    
    LCD_SendCommand(0xDF);
    LCD_SendData(0x21);
    LCD_SendData(0x0c);
    LCD_SendData(0x02);
    
    LCD_SendCommand(0xF0);
    LCD_SendData(0x45);
    LCD_SendData(0x09);
    LCD_SendData(0x08);
    LCD_SendData(0x08);
    LCD_SendData(0x26);
    LCD_SendData(0x2A);
    
    LCD_SendCommand(0xF1);
    LCD_SendData(0x43);
    LCD_SendData(0x70);
    LCD_SendData(0x72);
    LCD_SendData(0x36);
    LCD_SendData(0x37);
    LCD_SendData(0x6F);
    
    
    LCD_SendCommand(0xF2);
    LCD_SendData(0x45);
    LCD_SendData(0x09);
    LCD_SendData(0x08);
    LCD_SendData(0x08);
    LCD_SendData(0x26);
    LCD_SendData(0x2A);
    
    LCD_SendCommand(0xF3);
    LCD_SendData(0x43);
    LCD_SendData(0x70);
    LCD_SendData(0x72);
    LCD_SendData(0x36);
    LCD_SendData(0x37);
    LCD_SendData(0x6F);
    
    LCD_SendCommand(0xED);
    LCD_SendData(0x1B);
    LCD_SendData(0x0B);
    
    LCD_SendCommand(0xAE);
    LCD_SendData(0x74);
    
    LCD_SendCommand(0xCD);
    LCD_SendData(0x63);
    
    
    LCD_SendCommand(0x70);
    LCD_SendData(0x07);
    LCD_SendData(0x09);
    LCD_SendData(0x04);
    LCD_SendData(0x0E);
    LCD_SendData(0x0F);
    LCD_SendData(0x09);
    LCD_SendData(0x07);
    LCD_SendData(0x08);
    LCD_SendData(0x03);
    
    LCD_SendCommand(0xE8);
    LCD_SendData(0x34);
    
    LCD_SendCommand(0x62);
    LCD_SendData(0x18);
    LCD_SendData(0x0D);
    LCD_SendData(0x71);
    LCD_SendData(0xED);
    LCD_SendData(0x70);
    LCD_SendData(0x70);
    LCD_SendData(0x18);
    LCD_SendData(0x0F);
    LCD_SendData(0x71);
    LCD_SendData(0xEF);
    LCD_SendData(0x70);
    LCD_SendData(0x70);
    
    LCD_SendCommand(0x63);
    LCD_SendData(0x18);
    LCD_SendData(0x11);
    LCD_SendData(0x71);
    LCD_SendData(0xF1);
    LCD_SendData(0x70);
    LCD_SendData(0x70);
    LCD_SendData(0x18);
    LCD_SendData(0x13);
    LCD_SendData(0x71);
    LCD_SendData(0xF3);
    LCD_SendData(0x70);
    LCD_SendData(0x70);
    
    LCD_SendCommand(0x64);
    LCD_SendData(0x28);
    LCD_SendData(0x29);
    LCD_SendData(0xF1);
    LCD_SendData(0x01);
    LCD_SendData(0xF1);
    LCD_SendData(0x00);
    LCD_SendData(0x07);
    
    LCD_SendCommand(0x66);
    LCD_SendData(0x3C);
    LCD_SendData(0x00);
    LCD_SendData(0xCD);
    LCD_SendData(0x67);
    LCD_SendData(0x45);
    LCD_SendData(0x45);
    LCD_SendData(0x10);
    LCD_SendData(0x00);
    LCD_SendData(0x00);
    LCD_SendData(0x00);
    
    LCD_SendCommand(0x67);
    LCD_SendData(0x00);
    LCD_SendData(0x3C);
    LCD_SendData(0x00);
    LCD_SendData(0x00);
    LCD_SendData(0x00);
    LCD_SendData(0x01);
    LCD_SendData(0x54);
    LCD_SendData(0x10);
    LCD_SendData(0x32);
    LCD_SendData(0x98);
    
    LCD_SendCommand(0x74);
    LCD_SendData(0x10);
    LCD_SendData(0x85);
    LCD_SendData(0x80);
    LCD_SendData(0x00);
    LCD_SendData(0x00);
    LCD_SendData(0x4E);
    LCD_SendData(0x00);
    
    LCD_SendCommand(0x98);
    LCD_SendData(0x3e);
    LCD_SendData(0x07);
    
    
    
    LCD_SendCommand(0x35);
    LCD_SendCommand(0x21);
    HAL_Delay(120);
    //--------endgammasetting--------------//
    
    LCD_SendCommand(0x11);
    HAL_Delay(320);
    LCD_SendCommand(0x29);
    HAL_Delay(120);
    LCD_SendCommand(0x2C);
    
		
}

void LCD_SetAddressWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
    uint8_t temp[4] = {0,x0,x1>>8,x1};
		
    LCD_SendCommand(0x2A); // Column Address Set
    HAL_GPIO_WritePin(rs_port, rs_pin, GPIO_PIN_SET);
    HAL_SPI_Transmit_DMA(&hspi1, temp, sizeof(temp));

    LCD_SendCommand(0x2B); // Page Address Set
    HAL_GPIO_WritePin(rs_port, rs_pin, GPIO_PIN_SET);
    temp[1] = y0;
    temp[3] = y1;
    HAL_SPI_Transmit_DMA(&hspi1, temp, sizeof(temp));

    LCD_SendCommand(0x2C); // Memory Write
}


void LCD_DrawPixel(uint16_t x, uint16_t y, uint16_t color) {
    LCD_SetAddressWindow(x, y, x, y);
    LCD_SendData((color >> 8) & 0xFF);
    LCD_SendData(color & 0xFF);
}

void LCD_FillRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) {
    LCD_SetAddressWindow(x, y, x + w - 1, y + h - 1);
    uint32_t size = (uint32_t)w * h;
    size = h;
    HAL_GPIO_WritePin(rs_port, rs_pin, GPIO_PIN_SET);
    for(int i = 0;i<h;i++){
        for(int j = 0;j<w*2;j+=2){
            lcd_disp_area[j] = color>>8;
            lcd_disp_area[j + 1] = color;
        }
				LCD_SendDataBuf(lcd_disp_area,sizeof(lcd_disp_area));
				while(hspi1.State == HAL_SPI_STATE_BUSY_TX){
				};
    }
}

void LCD_Clear(uint16_t color) {
    LCD_FillRect(0, 0, LCD_WIDTH, LCD_HEIGHT, color);
}

